<template>
  <div class="content-tree" :style="{ maxHeight: autoHeight + 'px', minHeight: autoHeight + 'px' }">
    <div style="padding-top: 3px">
      <div class="btn-group" style="text-align: right; margin-right: 6px; margin-bottom: 3px">
        <Button type="primary" @click="newMenu(0)"> <FileAddOutlined /> 添加 </Button>
        <Button type="primary" ghost @click="newMenu(menu.Id)" :disabled="!menu.Id"> <FileAddOutlined /> 添加子菜单 </Button>
        <Button type="primary" danger :disabled="!menu.Id"> <DeleteOutlined /> 删除 </Button>
      </div>
      <Tree :tree-data="treeDatas" @select="onSelect" v-model:selected-keys="selectedKeys" :height="autoHeight - 40" :virtual="false" v-model:expanded-keys="expandedKeys" :showLine="true" :show-icon="true">
      </Tree>
    </div>
    <div>
      <Form layout="horizontal" :label-col="{ style: { width: '100px' } }">
        <Form.Item label="编号">
          <Input v-model:value="menu.Id" :disabled="true" placeholder="编号" />
        </Form.Item>
        <Form.Item label="名称">
          <Input v-model:value="menu.Name" placeholder="名称" />
        </Form.Item>
        <Form.Item label="访问地址">
          <Input v-model:value="menu.Url" placeholder="访问地址" />
        </Form.Item>
        <Form.Item label="上级菜单">
          <TreeSelect v-model:value="menu.ParentId" tree-default-expand-all :tree-data="parentTreeDatas" @dropdown-visible-change="changeState" />
        </Form.Item>
        <Form.Item label="图标">
          <Input v-model:value="menu.Icon" placeholder="图标" />
        </Form.Item>
        <Form.Item label="可见">
          <Switch v-model:checked="menu.Visible" :checked-value="1" :un-checked-value="0" />
        </Form.Item>
        <Form.Item label="排序值">
          <Input v-model:value="menu.SortValue" placeholder="排序值" />
        </Form.Item>
        <Form.Item label="操作点">
          <div class="ops">
            <div>
              <Button v-for="(tag, index) of menu.Tags" shape="round">
                {{ tag }}
                <DeleteOutlined @click="closeTag(index)" />
              </Button>
            </div>
            <Button type="primary" shape="circle" @click="showOperator = true">
              <PlusOutlined />
            </Button>
          </div>
        </Form.Item>
        <Form.Item>
          <div style="margin-left: 100px">
            <Button type="primary" shape="round" @click="saveMenu"> <SaveOutlined /> 保存 </Button>
          </div>
        </Form.Item>
      </Form>
    </div>
  </div>
  <Modal v-model:visible="showOperator" @ok="saveTag()" title="添加操作点" centered :maskClosable="false" :width="500">
    <Form.Item label="操作点">
      <Input v-model:value="tags" placeholder="请输入操作点(多个时用“,”分隔)" />
    </Form.Item>
  </Modal>
</template>
<script setup>
  import { useStore } from 'vuex';
  import { inject, ref, watch, reactive, onMounted } from 'vue';
  import { Tree, Form, Input, TreeSelect, Switch, Button, Tag, Modal } from 'ant-design-vue';
  import { FileAddOutlined, SaveOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';

  const $store = useStore();

  const $http = inject('$http');
  const $modal = inject('$modal');
  const $message = inject('$message');
  const $eventBus = inject('$eventBus');

  const tags = ref('');
  const autoHeight = ref(400);
  const showOperator = ref(false);

  const menus = ref([]);
  const treeDatas = ref([]);
  const expandedKeys = ref([]);
  const selectedKeys = ref([]);
  const parentTreeDatas = ref([]);

  const menu = reactive({
    Tags: []
  });

  function getMenus() {
    menus.value.length = 0;
    expandedKeys.value.length = 0;

    $http.get('/api/menu/all').then(res => {
      menus.value = res.datas || [];

      let roots = buildTreeDatas(menus.value);

      treeDatas.value = roots;
      parentTreeDatas.value = [{ title: '顶级菜单', value: 0, children: JSON.parse(JSON.stringify(roots)) }];

      selectedKeys.value[0] = expandedKeys.value[0];

      onSelect(expandedKeys.value[0]);
    });
  }

  function changeState() {
    if (menu.Id) {
      let item = findMenu(parentTreeDatas.value, menu.Id);

      console.log(menu.Id, item);

      if (item) {
        item.disabled = true;
      }
    }
  }

  function onSelect(key) {
    let item = menus.value.find(m => m.Id == key);

    if (item) {
      let props = Object.keys(item);

      menu.Tags.length = 0;
      props.forEach(p => (menu[p] = item[p]));

      if (menu.Operators) {
        menu.Tags.push(...menu.Operators.split(','));
      }
    }
  }

  function newMenu(parentId = 0) {
    menu.Id = -1;
    menu.ParentId = parentId || menu.ParentId;
    menu.Name = '';
    menu.Url = '';
    menu.Icon = '';
    menu.Visible = 1;
    menu.SortValue = 0;
    menu.Tags.length = 0;
  }

  function closeTag(index) {
    menu.Tags.splice(index, 1);
  }

  function saveTag() {
    if (tags.value) {
      let items = tags.value.split(',');

      menu.Tags.push(...items);

      tags.value = '';
      showOperator.value = false;
    }
  }

  function saveMenu() {
    if (!menu.Name || !menu.Name.trim()) {
      $message.warning({ key: 'valid', content: '名称为不能为空！' });

      return;
    }

    $http
      .post('/api/menu/save', {
        id: menu.Id,
        name: menu.Name,
        url: menu.Url,
        parentId: menu.ParentId,
        icon: menu.Icon,
        visible: menu.Visible == null ? 1 : menu.Visible,
        sortValue: menu.SortValue || 0,
        operators: menu.Tags.join(',')
      })
      .then(rs => {
        if (rs.success) {
          $message.success('保存成功！');
          getMenus();
        } else {
          $message.error('出现错误，错误原因：' + rs.message);
        }
      });
  }

  function buildTreeDatas(datas, parentId) {
    if (!datas || datas.length == 0) {
      return [];
    }

    if (!parentId) {
      return datas
        .filter(d => !d.ParentId)
        .map(d => {
          let rs = { key: '' + d.Id, title: d.Name, value: d.Id };

          expandedKeys.value.push(rs.key);
          rs.children = buildTreeDatas(datas, d.Id);

          return rs;
        });
    } else {
      return datas
        .filter(d => d.ParentId == parentId)
        .map(d => {
          let rs = { key: '' + d.Id, title: d.Name, value: d.Id };

          expandedKeys.value.push(rs.key);
          rs.children = buildTreeDatas(datas, d.Id);

          return rs;
        });
    }
  }

  function findMenu(datas, id) {
    if (datas.length == 0) {
      return null;
    }

    datas.forEach(d => (d.disabled = false));

    let item = datas.find(t => t.value == id);

    if (item != null) {
      return item;
    }

    for (let d of datas) {
      item = findMenu(d.children, id);

      if (item) {
        break;
      }
    }

    return item;
  }

  onMounted(() => {
    getMenus();

    autoHeight.value = $store.state.area.content.height - 40;
    $eventBus.on('windowResizeChanged', client => (autoHeight.value = client.height - 40));
  });
</script>

<style lang="less" scoped>
  .content-tree {
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
    background: transparent !important;

    > div {
      padding-top: 10px;
      padding-bottom: 10px;
      background: #ffffff;
      border-radius: 5px;

      &:first-of-type {
        width: 350px;
        padding-left: 10px;
      }

      &:last-of-type {
        flex: 0 0 calc(100% - 360px);
        padding-right: 20px;
      }
    }
  }

  .ops {
    display: flex;
    flex-flow: row wrap;
    align-items: center;
    justify-content: space-between;

    > div {
      button {
        color: #1890ff;
        border: 1px solid #1890ff;
        margin-right: 10px;

        &:last-of-type {
          margin-right: 0;
        }

        > .anticon {
          font-size: 18px;
          position: relative;
          top: 2px;
          right: -10px;
          color: red;
        }
      }
    }
  }
</style>
